<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>DongTian WebSocket 客户端示例</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        .container {
            display: flex;
            flex-direction: column;
            height: 100vh;
        }
        .connection-status {
            padding: 10px;
            margin-bottom: 10px;
            border-radius: 5px;
        }
        .connected {
            background-color: #d4edda;
            color: #155724;
        }
        .disconnected {
            background-color: #f8d7da;
            color: #721c24;
        }
        .log-container {
            flex-grow: 1;
            border: 1px solid #ccc;
            padding: 10px;
            overflow-y: auto;
            background-color: #f8f9fa;
            margin-bottom: 10px;
            border-radius: 5px;
        }
        .controls {
            display: flex;
            flex-direction: column;
            gap: 10px;
        }
        .input-group {
            display: flex;
            gap: 10px;
        }
        input, button, select {
            padding: 8px;
            border-radius: 5px;
            border: 1px solid #ccc;
        }
        input {
            flex-grow: 1;
        }
        button {
            background-color: #007bff;
            color: white;
            border: none;
            cursor: pointer;
        }
        button:hover {
            background-color: #0069d9;
        }
        button:disabled {
            background-color: #6c757d;
            cursor: not-allowed;
        }
        .message {
            margin: 5px 0;
            padding: 5px;
            border-radius: 3px;
        }
        .received {
            background-color: #e2f3f5;
        }
        .sent {
            background-color: #d4f1c5;
        }
        .ping {
            background-color: #ffe8cc;
            color: #856404;
        }
        .pong {
            background-color: #d1ecf1;
            color: #0c5460;
        }
        .heartbeat-monitor {
            margin-top: 10px;
            padding: 10px;
            border: 1px solid #ccc;
            border-radius: 5px;
            background-color: #f8f9fa;
        }
        .heartbeat-status {
            display: flex;
            justify-content: space-between;
            margin-bottom: 10px;
        }
        .status-item {
            display: flex;
            flex-direction: column;
            align-items: center;
        }
        .status-label {
            font-weight: bold;
            margin-bottom: 5px;
        }
        .status-value {
            font-size: 1.2em;
        }
        .checkbox-group {
            display: flex;
            gap: 10px;
            align-items: center;
            margin-top: 10px;
        }
        .checkbox-group input {
            width: auto;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>DongTian WebSocket 客户端示例</h1>
        
        <div id="status" class="connection-status disconnected">
            未连接
        </div>
        
        <div class="controls">
            <div class="input-group">
                <input type="text" id="serverUrl" value="ws://localhost:7789/meeting" placeholder="WebSocket 服务器地址">
                <button id="connectBtn">连接</button>
                <button id="disconnectBtn" disabled>断开</button>
            </div>
            
            <div class="input-group">
                <input type="text" id="roomName" placeholder="房间名称">
                <button id="joinRoomBtn" disabled>加入房间</button>
            </div>
        </div>
        
        <div class="heartbeat-monitor">
            <h3>心跳监控</h3>
            <div class="heartbeat-status">
                <div class="status-item">
                    <div class="status-label">上次Ping</div>
                    <div class="status-value" id="lastPing">-</div>
                </div>
                <div class="status-item">
                    <div class="status-label">上次Pong</div>
                    <div class="status-value" id="lastPong">-</div>
                </div>
                <div class="status-item">
                    <div class="status-label">Ping计数</div>
                    <div class="status-value" id="pingCount">0</div>
                </div>
                <div class="status-item">
                    <div class="status-label">Pong计数</div>
                    <div class="status-value" id="pongCount">0</div>
                </div>
            </div>
            <div class="checkbox-group">
                <input type="checkbox" id="logHeartbeat" checked>
                <label for="logHeartbeat">记录心跳消息</label>
                
                <input type="checkbox" id="respondToPing" checked>
                <label for="respondToPing">响应Ping消息</label>
            </div>
        </div>
        
        <h3>消息日志</h3>
        <div id="log" class="log-container"></div>
        
        <div class="controls">
            <div class="input-group">
                <select id="messageType">
                    <option value="10">请求成为房主</option>
                    <option value="11">同意房主请求</option>
                    <option value="12">更改播放文件</option>
                    <option value="13">更改播放状态</option>
                    <option value="14">对象同步</option>
                </select>
                <input type="text" id="messageData" placeholder="消息数据 (JSON 格式)">
                <button id="sendBtn" disabled>发送</button>
            </div>
        </div>
    </div>

    <script>
        let socket = null;
        let clientId = null;
        let pingCount = 0;
        let pongCount = 0;
        
        // 命令类型枚举
        const Command = {
            NONE: 0,
            JOIN_ROOM: 1,
            ASK_ROOM_OWNER: 2,
            CONNECT_SUCCESS: 3,
            ROOM_JOIN_ROOM: 4,
            ROOM_LEAVE_ROOM: 5,
            ROOM_BROADCAST: 6,
            ROOM_REQUEST_ROOM_OWNER: 7,
            ROOM_ROOM_OWNER_CHANGE: 8,
            ROOM_CHANGE_PLAY_ROOM_FILE: 9,
            ROOM_RESPONCE_ROOM_OWNER_REQUEST: 10,
            ROOM_GET_ALL_USER_INFO: 11,
            ROOM_CHANGE_PLAY_STATE: 12,
            ROOM_OBJ_SYNCHRONIZATION: 13,
            ROOM_STATE_SEND_TO_USER: 14,
            ROOM_MULTI_OBJ_SYNC: 16
        };
        
        // DOM 元素
        const statusEl = document.getElementById('status');
        const connectBtn = document.getElementById('connectBtn');
        const disconnectBtn = document.getElementById('disconnectBtn');
        const joinRoomBtn = document.getElementById('joinRoomBtn');
        const sendBtn = document.getElementById('sendBtn');
        const logEl = document.getElementById('log');
        const serverUrlEl = document.getElementById('serverUrl');
        const roomNameEl = document.getElementById('roomName');
        const messageTypeEl = document.getElementById('messageType');
        const messageDataEl = document.getElementById('messageData');
        const lastPingEl = document.getElementById('lastPing');
        const lastPongEl = document.getElementById('lastPong');
        const pingCountEl = document.getElementById('pingCount');
        const pongCountEl = document.getElementById('pongCount');
        const logHeartbeatEl = document.getElementById('logHeartbeat');
        const respondToPingEl = document.getElementById('respondToPing');
        
        // 连接按钮点击事件
        connectBtn.addEventListener('click', () => {
            connect(serverUrlEl.value);
        });
        
        // 断开按钮点击事件
        disconnectBtn.addEventListener('click', () => {
            disconnect();
        });
        
        // 加入房间按钮点击事件
        joinRoomBtn.addEventListener('click', () => {
            const roomName = roomNameEl.value.trim();
            if (roomName) {
                joinRoom(roomName);
            } else {
                logMessage('请输入房间名称', 'error');
            }
        });
        
        // 发送按钮点击事件
        sendBtn.addEventListener('click', () => {
            const messageType = parseInt(messageTypeEl.value);
            let messageData = messageDataEl.value.trim();
            
            if (!messageData) {
                messageData = '{}';
            }
            
            try {
                // 验证JSON格式
                JSON.parse(messageData);
                sendMessage(messageType, messageData);
            } catch (e) {
                logMessage('无效的JSON格式: ' + e.message, 'error');
            }
        });
        
        // 连接到WebSocket服务器
        function connect(url) {
            if (socket) {
                socket.close();
            }
            
            try {
                // 重置计数器
                pingCount = 0;
                pongCount = 0;
                updateHeartbeatDisplay();
                
                socket = new WebSocket(url);
                
                socket.onopen = () => {
                    setConnected(true);
                    logMessage('已连接到服务器', 'info');
                };
                
                socket.onclose = (event) => {
                    setConnected(false);
                    logMessage(`连接已关闭: ${event.code} ${event.reason}`, 'info');
                    clientId = null;
                };
                
                socket.onerror = (error) => {
                    logMessage('WebSocket错误', 'error');
                };
                
                socket.onmessage = (event) => {
                    handleMessage(event.data);
                };
                
                // 添加ping处理程序
                socket.addEventListener('ping', (event) => {
                    pingCount++;
                    lastPingEl.textContent = new Date().toLocaleTimeString();
                    updateHeartbeatDisplay();
                    
                    if (logHeartbeatEl.checked) {
                        logMessage('收到Ping', 'ping');
                    }
                    
                    // 如果设置了响应ping，则发送pong
                    if (respondToPingEl.checked) {
                        // WebSocket API会自动响应ping，无需手动处理
                    }
                });
            } catch (error) {
                logMessage('连接错误: ' + error.message, 'error');
            }
        }
        
        // 更新心跳显示
        function updateHeartbeatDisplay() {
            pingCountEl.textContent = pingCount;
            pongCountEl.textContent = pongCount;
        }
        
        // 断开连接
        function disconnect() {
            if (socket) {
                socket.close();
                socket = null;
            }
        }
        
        // 加入房间
        function joinRoom(roomName) {
            if (!socket || socket.readyState !== WebSocket.OPEN) {
                logMessage('未连接到服务器', 'error');
                return;
            }
            
            const data = {
                room: roomName,
                userid: clientId
            };
            
            sendMessage(Command.JOIN_ROOM, JSON.stringify(data));
            logMessage(`请求加入房间: ${roomName}`, 'sent');
        }
        
        // 发送消息
        function sendMessage(cmd, data) {
            if (!socket || socket.readyState !== WebSocket.OPEN) {
                logMessage('未连接到服务器', 'error');
                return;
            }
            
            const message = {
                cmd: cmd,
                data: data
            };
            
            socket.send(JSON.stringify(message));
            logMessage(`已发送: ${JSON.stringify(message)}`, 'sent');
        }
        
        // 处理接收到的消息
        function handleMessage(data) {
            try {
                const message = JSON.parse(data);
                logMessage(`已接收: ${data}`, 'received');
                
                switch (message.cmd) {
                    case Command.CONNECT_SUCCESS:
                        const connectInfo = JSON.parse(message.data);
                        clientId = connectInfo.userid;
                        logMessage(`连接成功，客户端ID: ${clientId}`, 'info');
                        break;
                        
                    case Command.ROOM_JOIN_ROOM:
                        logMessage(`用户 ${message.data} 已加入房间`, 'info');
                        break;
                        
                    case Command.ROOM_LEAVE_ROOM:
                        logMessage(`用户 ${message.data} 已离开房间`, 'info');
                        break;
                        
                    case Command.ROOM_ROOM_OWNER_CHANGE:
                        logMessage(`房主已更改为: ${message.data}`, 'info');
                        break;
                        
                    case Command.ROOM_REQUEST_ROOM_OWNER:
                        logMessage(`用户 ${message.data} 请求成为房主`, 'info');
                        break;
                        
                    case Command.ROOM_CHANGE_PLAY_ROOM_FILE:
                        logMessage(`播放文件已更改为: ${message.data}`, 'info');
                        break;
                        
                    case Command.ROOM_CHANGE_PLAY_STATE:
                        logMessage(`播放状态已更改: ${message.data}`, 'info');
                        break;
                        
                    case Command.ROOM_OBJ_SYNCHRONIZATION:
                        logMessage(`对象同步: ${message.data}`, 'info');
                        break;

                    case Command.ROOM_MULTI_OBJ_SYNC:
                        logMessage(`多对象同步: ${message.data}`, 'info');
                        break;
                        
                    default:
                        logMessage(`未知命令: ${message.cmd}`, 'info');
                }
            } catch (e) {
                logMessage('解析消息错误: ' + e.message, 'error');
            }
        }
        
        // 设置连接状态
        function setConnected(connected) {
            if (connected) {
                statusEl.textContent = '已连接';
                statusEl.className = 'connection-status connected';
                connectBtn.disabled = true;
                disconnectBtn.disabled = false;
                joinRoomBtn.disabled = false;
                sendBtn.disabled = false;
            } else {
                statusEl.textContent = '未连接';
                statusEl.className = 'connection-status disconnected';
                connectBtn.disabled = false;
                disconnectBtn.disabled = true;
                joinRoomBtn.disabled = true;
                sendBtn.disabled = true;
                
                // 重置心跳显示
                lastPingEl.textContent = '-';
                lastPongEl.textContent = '-';
            }
        }
        
        // 记录消息
        function logMessage(message, type) {
            const msgEl = document.createElement('div');
            msgEl.className = `message ${type}`;
            msgEl.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
            logEl.appendChild(msgEl);
            logEl.scrollTop = logEl.scrollHeight;
        }
    </script>
</body>
</html> 